home *** CD-ROM | disk | FTP | other *** search
/ Monster Media 1996 #14 / Monster Media No. 14 (April 1996) (Monster Media, Inc.).ISO / prog_d / mdboutln.zip / MAIN.PAS < prev    next >
Pascal/Delphi Source File  |  1995-11-27  |  20KB  |  547 lines

  1. unit Main;
  2.  
  3. { Copyright ⌐ 1995 Maelstrom Software.  This program may be freely distributed.
  4.   Any code within the program may be re-used in any manner by registered users
  5.   of Maelstrom TDBOutline. }
  6.  
  7. interface
  8.  
  9. uses
  10.   SysUtils, WinTypes, WinProcs, Messages, Classes, Graphics, Controls,
  11.   Forms, Dialogs, StdCtrls, Buttons, ExtCtrls, Menus, DBCtrls,
  12.   Grids, Outline, DBOutln, DB, DBTables, Mask, TabNotBk, About, DBGrids,
  13.   AEEmp;
  14.  
  15. type
  16.   ETableNotFound = class(Exception);
  17.  
  18.   TfrmMainForm = class(TForm)
  19.     pnlSpeedBar: TPanel;
  20.     ntbktabDemo: TTabbedNotebook;
  21.     tblNotes: TTable;
  22.     tblEmployees: TTable;
  23.     dtasrcNotes: TDataSource;
  24.     dtasrcEmployees: TDataSource;
  25.     dtasrcTasks: TDataSource;
  26.     pnlNotes: TPanel;
  27.     pnlEmployees: TPanel;
  28.     pnlTasks: TPanel;
  29.     pnlNotesSplitter: TPanel;
  30.     pnlEmployeesSplitter: TPanel;
  31.     DBOutlineNotes: TDBOutline;
  32.     DBOutlineEmployees: TDBOutline;
  33.     DBOutlineTasks: TDBOutline;
  34.     btnspdAbout: TSpeedButton;
  35.     btnspdHelp: TSpeedButton;
  36.     tblEmployeesEmpNo: TIntegerField;
  37.     tblEmployeesLastName: TStringField;
  38.     tblEmployeesFirstName: TStringField;
  39.     tblEmployeesPhoneExt: TStringField;
  40.     tblEmployeesHireDate: TDateTimeField;
  41.     tblEmployeesSalary: TFloatField;
  42.     tblEmployeesSupervisor: TIntegerField;
  43.     tblEmployeesFullName: TStringField;
  44.     bxmemodbNotes: TDBMemo;
  45.     grddbEmployees: TDBGrid;
  46.     pmnuEmployees: TPopupMenu;
  47.     pmnuitemAddChild: TMenuItem;
  48.     pmnuitemAddSibling: TMenuItem;
  49.     pmnuitemSeparator1: TMenuItem;
  50.     pmnuitemDelete: TMenuItem;
  51.     pmnuitemEdit: TMenuItem;
  52.     pmnuitemSeparator2: TMenuItem;
  53.     pnlMoveSplitterNotes: TPanel;
  54.     pnlMoveSplitterEmployees: TPanel;
  55.     pnlTaskSplitter: TPanel;
  56.     pnlMoveSplitterTasks: TPanel;
  57.     qryTasks: TQuery;
  58.     grddbTasks: TDBGrid;
  59.     qryTasksProjectTaskName: TStringField;
  60.     qryTasksProjectTaskNumber: TIntegerField;
  61.     qryTasksProjectTaskType: TStringField;
  62.     qryTasksProjectTaskOrder: TIntegerField;
  63.     qryTasksProjectTaskNote: TMemoField;
  64.     qryTasksOwningTaskNumber: TIntegerField;
  65.     pnlTaskMemo: TPanel;
  66.     bxmemodbTasks: TDBMemo;
  67.     Memo1: TMemo;
  68.     pnlEmployeeFooter: TPanel;
  69.     btnSaveDragDropChanges: TButton;
  70.     btnCancelDragDropChanges: TButton;
  71.     DBNavigatorEmployees: TDBNavigator;
  72.     pnlNotesFooter: TPanel;
  73.     DBNavigatorNotes: TDBNavigator;
  74.     pnlTaskFooter: TPanel;
  75.     DBNavigatorTasks: TDBNavigator;
  76.     procedure FormCreate(Sender: TObject);
  77.     procedure ShowHint(Sender: TObject);
  78.     procedure tblEmployeesCalcFields(DataSet: TDataset);
  79.     procedure btnspdAboutClick(Sender: TObject);
  80.     procedure btnspdHelpClick(Sender: TObject);
  81.     procedure DBOutlineEmployeesDragDrop(Sender, Source: TObject; X, Y: Integer);
  82.     procedure DBOutlineTasksDragDrop(Sender, Source: TObject; X, Y: Integer);
  83.     procedure DBOutlineEmployeesAutoDragDrop(Sender: TObject; var Accept: Boolean;
  84.       var FromNode, ToNode: OpenString);
  85.     procedure DBOutlineTasksAutoDragDrop(Sender: TObject; var Accept: Boolean;
  86.       var FromNode, ToNode: OpenString);
  87.     procedure DBOutlineEmployeesMouseUp(Sender: TObject; Button: TMouseButton;
  88.       Shift: TShiftState; X, Y: Integer);
  89.     procedure pmnuitemAddChildClick(Sender: TObject);
  90.     procedure pmnuitemEditClick(Sender: TObject);
  91.     procedure pmnuitemDeleteClick(Sender: TObject);
  92.     function GetDatabaseName: string;
  93.     procedure pnlSplitterMouseDown(Sender: TObject;
  94.       Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
  95.     procedure pnlSplitterMouseMove(Sender: TObject;
  96.       Shift: TShiftState; X, Y: Integer);
  97.     procedure pnlSplitterMouseUp(Sender: TObject;
  98.       Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
  99.     procedure FormResize(Sender: TObject);
  100.     procedure DBOutlineEmployeesDragOver(Sender, Source: TObject; X,
  101.       Y: Integer; State: TDragState; var Accept: Boolean);
  102.     procedure DBOutlineTasksDragOver(Sender, Source: TObject; X,
  103.       Y: Integer; State: TDragState; var Accept: Boolean);
  104.     procedure DBOutlineTasksMouseUp(Sender: TObject; Button: TMouseButton;
  105.       Shift: TShiftState; X, Y: Integer);
  106.     procedure btnSaveDragDropChangesClick(Sender: TObject);
  107.     procedure btnCancelDragDropChangesClick(Sender: TObject);
  108.     procedure dtasrcNotesDataChange(Sender: TObject; Field: TField);
  109.     procedure dtasrcEmployeesDataChange(Sender: TObject; Field: TField);
  110.     procedure dtasrcTasksDataChange(Sender: TObject; Field: TField);
  111.   end;
  112.  
  113. var
  114.   frmMainForm: TfrmMainForm;
  115.   StartSynching:         Boolean;
  116.   { the following vars are for use in the splitter bars of the demo program.
  117.     they are not related to the use of TDBOutline.}
  118.   pnlSendingSplitter:    TPanel;
  119.   pnlMovingSplitter:     TPanel;
  120.   otlnedbObjectToResize: TDBOutline;
  121.   pnlParentPanel:        TPanel;
  122.   boolResizeInProgress:  Boolean;
  123.   FirstLoad:             Boolean;
  124.  
  125. implementation
  126.  
  127. {$R *.DFM}
  128.  
  129. {-------------------------------------------------}
  130. procedure TfrmMainForm.FormCreate(Sender: TObject);
  131. var
  132.   strDataBaseName: string;
  133. begin
  134.   { the following block of code is used to set up the demo -- not
  135.     related to the use of TDBOutline }
  136.   Application.OnHint         := ShowHint;
  137.   Application.HelpFile       := 'TDBOutli.hlp';
  138.   Application.ShowHint       := false;
  139.   strDatabaseName            := GetDatabaseName;
  140.   tblNotes.DatabaseName      := strDatabaseName;
  141.   tblEmployees.DatabaseName  := strDatabaseName;
  142.   qryTasks.DatabaseName      := strDatabaseName;
  143.   if not FileExists(tblNotes.DatabaseName + '\' + tblNotes.TableName) then
  144.     raise ETableNotFound.Create('Notes table cannot be located');
  145.   if not FileExists(tblEmployees.DatabaseName + '\' + tblEmployees.TableName) then
  146.     raise ETableNotFound.Create('Employees table cannot be located');
  147.   if not FileExists(qryTasks.DatabaseName + '\' + 'project.db') then
  148.     raise ETableNotFound.Create('Project Tasks table cannot be located');
  149.  
  150.   { to prevent OnDataChange event of the DataSource from
  151.     synchronizing the DBOutline during initial load }
  152.   StartSynching := false;
  153.   { open the tables/queries -- must be open to execute method LoadFromDataSet }
  154.   tblNotes.Open;
  155.   tblEmployees.Open;
  156.   qryTasks.Open;
  157.  
  158.   { call method LoadFromDataSet for each dataset: this single method }
  159.   { performs the load of hierarchical data into the outline}
  160.   DBOutlineNotes.LoadFromDataSet;
  161.   DBOutlineEmployees.LoadFromDataSet;
  162.   DBOutlineTasks.LoadFromDataSet;
  163.  
  164.   {Expand the Employee MasterParent, and select the first employee }
  165.   if DBOutlineEmployees.ItemCount > 1 then
  166.   begin
  167.     DBOutlineEmployees.Items[1].Expand;
  168.     DBOutlineEmployees.SelectedItem := 2;
  169.   end;
  170.  
  171.   {Expand the Task MasterParent, and selecte the first employee }
  172.   if DBOutlineTasks.ItemCount > 1 then
  173.   begin
  174.     DBOutlineTasks.Items[1].Expand;
  175.     DBOutlineTasks.SelectedItem := 2;
  176.   end;
  177.  
  178.   { to start OnDataChange event of the DataSources synchronizing
  179.     the DBOutline }
  180.   StartSynching := true;
  181.  
  182.   { the following vars used for the panel splitters in the demo
  183.     - not related to TDBOutline use.}
  184.   pnlMovingSplitter := pnlMoveSplitterNotes;
  185.   otlnedbObjectToResize := DBOutlineNotes;
  186.   pnlParentPanel := pnlNotes;
  187.   FirstLoad := true;
  188. end;
  189.  
  190. {-------------------------------------------------}
  191. procedure TfrmMainForm.ShowHint(Sender: TObject);
  192. begin
  193.   Memo1.Clear;
  194.   Memo1.Lines[0] := Application.Hint;
  195. end;
  196.  
  197. {-------------------------------------------------}
  198. procedure TfrmMainForm.tblEmployeesCalcFields(DataSet: TDataset);
  199. begin
  200.   { this calculated field is used as property DataFieldDisplay in the
  201.     Employees example }
  202.   tblEmployeesFullName.AsString := tblEmployeesLastName.AsString
  203.     + ', ' + tblEmployeesFirstName.AsString;
  204. end;
  205.  
  206. {-------------------------------------------------}
  207. procedure TfrmMainForm.btnspdAboutClick(Sender: TObject);
  208. begin
  209.   frmAboutBox.ShowModal;
  210. end;
  211.  
  212. {-------------------------------------------------}
  213. procedure TfrmMainForm.btnspdHelpClick(Sender: TObject);
  214. begin
  215.   Application.HelpCommand(HELP_CONTENTS, 0);
  216. end;
  217.  
  218. {-------------------------------------------------}
  219. procedure TfrmMainForm.DBOutlineEmployeesDragOver(Sender, Source: TObject;
  220.   X, Y: Integer; State: TDragState; var Accept: Boolean);
  221. begin
  222.   { for drag-drop in the Employees example }
  223.   if Source = DBOutlineEmployees then Accept := true;
  224. end;
  225.  
  226. {-------------------------------------------------}
  227. procedure TfrmMainForm.DBOutlineTasksDragOver(Sender, Source: TObject; X,
  228.   Y: Integer; State: TDragState; var Accept: Boolean);
  229. begin
  230.   { for drag-drop in the Tasks example }
  231.   if Source = DBOutlineTasks then Accept := true;
  232. end;
  233.  
  234. {-------------------------------------------------}
  235. procedure TfrmMainForm.DBOutlineEmployeesDragDrop(Sender, Source: TObject; X,
  236.   Y: Integer);
  237. begin
  238.   if Source = DBOutlineEmployees then
  239.     { AutoDrop is the single method call required to perform the move
  240.      of the node and update the database }
  241.     DBOutlineEmployees.AutoDrop(x, y);
  242. end;
  243.  
  244. {-------------------------------------------------}
  245. procedure TfrmMainForm.DBOutlineTasksDragDrop(Sender, Source: TObject; X,
  246.   Y: Integer);
  247. begin
  248.   if Source = DBOutlineTasks then
  249.     { AutoDrop is the single method call required to perform the move
  250.     of the node and update the database }
  251.     DBOutlineTasks.AutoDrop(x, y);
  252. end;
  253.  
  254. {-------------------------------------------------}
  255. procedure TfrmMainForm.DBOutlineTasksAutoDragDrop(Sender: TObject;
  256.   var Accept: Boolean; var FromNode, ToNode: OpenString);
  257. begin
  258.   { The event OnAutoDragDrop occurs just prior to the move of a node via
  259.     drag-drop.  This line overrides the default confirmation message presented
  260.     when a node is dragged-and-dropped. This ability gives the programmer control
  261.     over the confirmation message presented to the user.  In this case, we
  262.     override the default message and have no confirmation message displayed }
  263.   Accept := True;
  264. end;
  265.  
  266. {-------------------------------------------------}
  267. procedure TfrmMainForm.DBOutlineEmployeesAutoDragDrop(Sender: TObject;
  268.   var Accept: Boolean; var FromNode, ToNode: OpenString);
  269. var
  270.   strMessageText: string;
  271. begin
  272.  { this code overrides the default confirmation message presented when
  273.   a node is dragged-and-dropped, replacing it with the custom message.
  274.   This ability gives the programmer control over the confirmation
  275.   message presented to the user.}
  276.   strMessageText := 'This is a custom message defined in the OnAutoDragDrop event of TDBOutline.';
  277.   if MessageDlg(strMessageText + ' Have employee ['+FromNode+'] report to ['+ToNode+ ']?'
  278.     ,mtConfirmation, mbOkCancel,0) = mrOk
  279.     then Accept := true
  280.   else Accept := false
  281. end;
  282.  
  283. {-------------------------------------------------}
  284. procedure TfrmMainForm.DBOutlineEmployeesMouseUp(Sender: TObject;
  285.   Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
  286. begin
  287.   {SynchSuccess is a read-only runtime property of TDBOutline -- if true,
  288.    the database pointer was successfully synchronized with the selected node.
  289.    If false, it was not successfully synchronized.  In this example it is used
  290.    to hide the DBGrid if the MasterParent node is selected (the MasterParent
  291.    not having a corresponding record in the database) }
  292.   if DBOutlineEmployees.SynchSuccess then
  293.     begin
  294.       grddbEmployees.Visible := true;
  295.       StartSynching := true;
  296.     end
  297.   else
  298.     begin
  299.       grddbEmployees.Visible := false;
  300.       StartSynching := false;
  301.     end;
  302. end;
  303. {-------------------------------------------------}
  304. procedure TfrmMainForm.DBOutlineTasksMouseUp(Sender: TObject;
  305.   Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
  306. begin
  307.   if DBOutlineTasks.SynchSuccess then
  308.     begin
  309.       bxmemodbTasks.Visible := true;
  310.       grddbTasks.Visible := true;
  311.       StartSynching := true;
  312.     end
  313.   else
  314.     begin
  315.       bxmemodbTasks.Visible := false;
  316.       grddbTasks.Visible := false;
  317.       StartSynching := false;
  318.     end;
  319. end;
  320.  
  321. {-------------------------------------------------}
  322. procedure TfrmMainForm.dtasrcNotesDataChange(Sender: TObject;
  323.   Field: TField);
  324. begin
  325.   {SynchOutline is a TDBOutline method that synchronizes the selected
  326.    outline node with the currently selected record.  In this case, we
  327.    want the selected outline node to re-synch each time the datasource is
  328.    notified of any change (i.e., when the record pointer moves). StartSynching is
  329.    used in the Demo to prevent the DataSource from synchronizing the
  330.    DBOutline during the initial load, AddDBRecords, ChangeDBRecords,
  331.    Deletes etc. }
  332.   if StartSynching then
  333.     DBOutlineNotes.SynchOutline(Self);
  334. end;
  335. {-------------------------------------------------}
  336. procedure TfrmMainForm.dtasrcEmployeesDataChange(Sender: TObject;
  337.   Field: TField);
  338. begin
  339.   if StartSynching then
  340.     DBOutlineEmployees.SynchOutline(Self);
  341. end;
  342. {-------------------------------------------------}
  343. procedure TfrmMainForm.dtasrcTasksDataChange(Sender: TObject;
  344.   Field: TField);
  345. begin
  346.   if StartSynching then
  347.     DBOutlineTasks.SynchOutline(Self);
  348. end;
  349.  
  350. {-------------------------------------------------}
  351. procedure TfrmMainForm.pmnuitemAddChildClick(Sender: TObject);
  352. var
  353.   intParentEmpNo, intNewEmpNo: integer;
  354. begin
  355.   StartSynching := false;
  356.   { if popup menu option 'Add Child' was selected}
  357.   if Sender = pmnuitemAddChild then
  358.     begin
  359.       frmAEEmployee.Caption := 'Add Employee as Underling';
  360.       intParentEmpNo := tblEmployees.FieldByName('EmpNo').AsInteger;
  361.     end
  362.   { else if popup menu option 'Add Sibling' was selected}
  363.   else
  364.     begin;
  365.       frmAEEmployee.Caption := 'Add Employee as Peer';
  366.       intParentEmpNo := tblEmployees.FieldByName('Supervisor').AsInteger;
  367.     end;
  368.  
  369.  
  370.   {move to end of table (indexed on EmpNo) and increment last EmpNo by one.}
  371.   tblEmployees.Last;
  372.   intNewEmpNo := tblEmployees.FieldByName('EmpNo').AsInteger + 1;
  373.  
  374.   tblEmployees.Append;
  375.  
  376.   { if parent employee number is not 0, i.e. if you are not adding a peer
  377.     to a top-level parent }
  378.   if intParentEmpNo <> 0 then
  379.     tblEmployees.FieldByName('Supervisor').AsInteger := intParentEmpNo;
  380.  
  381.   tblEmployees.FieldByName('EmpNo').AsInteger := intNewEmpNo;
  382.  
  383.   frmAEEmployee.ShowModal;
  384.   { if OK button pressed to add to employee }
  385.   if frmAEEmployee.ModalResult=mrOK then
  386.     begin
  387.       if (tblEmployees.State = dsEdit) or (tblEmployees.State = dsInsert) then
  388.         begin
  389.           { Add new employee to database }
  390.           tblEmployees.Post;
  391.           { TDBOutline method to add current record (in this case, the new employee)
  392.             to the existing outline }
  393.           with tblEmployees do
  394.           DBOutlineEmployees.AddDBRecord(FieldByName('EmpNo').AsString,
  395.             FieldByName('FullName').AsString, FieldByName('Supervisor').AsString);
  396.         end;
  397.     end
  398.   else tblEmployees.Cancel;
  399.  
  400.   if DBOutlineEmployees.SynchSuccess then grddbEmployees.Visible := true
  401.   else grddbEmployees.Visible := false;
  402.   DBOutlineEmployees.SetFocus;
  403.   StartSynching := true;
  404. end;
  405.  
  406. {-------------------------------------------------}
  407. procedure TfrmMainForm.pmnuitemEditClick(Sender: TObject);
  408. var
  409.   OldEmpNo: string;
  410. begin
  411.   StartSynching := false;
  412.   frmAEEmployee.Caption := 'Edit Employee';
  413.   OldEmpNo := tblEmployees.FieldByName('EmpNo').AsString;
  414.   frmAEEmployee.ShowModal;
  415.   { if edit changes confirmed with OK button }
  416.   if frmAEEmployee.ModalResult=mrOK then
  417.     begin
  418.       if (tblEmployees.State = dsEdit) or (tblEmployees.State = dsInsert) then
  419.         begin
  420.           { post edit changes to database }
  421.           tblEmployees.Post;
  422.           { TDBOutline method to reinitialize node corresponding to the
  423.             currently selected record (in this case, the edited employee)
  424.             with the value of property DataFieldDisplay }
  425.           with tblEmployees do
  426.           DBOutlineEmployees.ChangeDBRecord(OldEmpNo, FieldByName('EmpNo').AsString,
  427.             FieldByName('FullName').AsString);
  428.         end;
  429.     end
  430.   else tblEmployees.Cancel;
  431.   DBOutlineEmployees.SetFocus;
  432.   StartSynching := true;
  433. end;
  434.  
  435. {-------------------------------------------------}
  436. procedure TfrmMainForm.pmnuitemDeleteClick(Sender: TObject);
  437. begin
  438.   StartSynching := false;
  439.   if messagedlg('Delete Employee [' + tblEmployees.FieldByName('FullName').AsString +
  440.     ']?',mtconfirmation,mbOKCancel,0) = mrOK then
  441.     begin
  442.     { !! be sure to delete the Table record first!!  If you delete the Outline node
  443.       first, then DataAutoSynch will move the datapointer to match the new
  444.       DBoutline.SelectedItem, and you'll end up deleting the wrong record! }
  445.       tblEmployees.Delete;
  446.       DBOutlineEmployees.Delete(DBOutlineEmployees.SelectedItem);
  447.     end;
  448.   DBOutlineEmployees.SetFocus;
  449.   StartSynching := true;
  450. end;
  451.  
  452. {-------------------------------------------------}
  453. procedure TfrmMainForm.btnSaveDragDropChangesClick(Sender: TObject);
  454. begin
  455.   { this method is used to post all drag-drop changes made to the DBOutline
  456.     that are outstanding (i.e., not posted to the dataset).  The method
  457.     can be used in conjunction with property DataAutoUpdate = false to allow
  458.     the user to manipulate the hierarchy without saving, then save or
  459.     abandon. }
  460.   DBOutlineEmployees.UpdateDraggedNodes(Self);
  461. end;
  462.  
  463. {-------------------------------------------------}
  464. procedure TfrmMainForm.btnCancelDragDropChangesClick(Sender: TObject);
  465. begin
  466.   { to abandon changes made via drag-drop (see above), if DataAutoUpdate = false,
  467.     just re-load the DBOutline. }
  468.   DBOutlineEmployees.LoadFromDataSet;
  469. end;
  470.  
  471.  
  472. { ************************************************************************ }
  473. { the remainder of this code is not related to the use of TDBOutline, but
  474.   rather to the functioning of the splitter bars in the demo program }
  475. {-------------------------------------------------}
  476. procedure TfrmMainForm.pnlSplitterMouseDown(Sender: TObject;
  477.   Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
  478. begin
  479.   if ntbktabDemo.PageIndex = 0 then
  480.   begin
  481.     pnlMovingSplitter := pnlMoveSplitterNotes;
  482.     otlnedbObjectToResize := DBOutlineNotes;
  483.     pnlParentPanel := pnlNotes;
  484.   end;
  485.   if ntbktabDemo.PageIndex = 1 then
  486.   begin
  487.     pnlMovingSplitter := pnlMoveSplitterEmployees;
  488.     otlnedbObjectToResize := DBOutlineEmployees;
  489.     pnlParentPanel := pnlEmployees;
  490.   end;
  491.   if ntbktabDemo.PageIndex = 2 then
  492.   begin
  493.     pnlMovingSplitter := pnlMoveSplitterTasks;
  494.     otlnedbObjectToResize := DBOutlineTasks;
  495.     pnlParentPanel := pnlTasks;
  496.   end;
  497.   pnlSendingSplitter := Sender as TPanel;
  498.   pnlMovingSplitter.Left := pnlSendingSplitter.Left;
  499.   pnlMovingSplitter.Height := pnlSendingSplitter.Height;
  500.   pnlMovingSplitter.Visible := true;
  501.   boolResizeInProgress := true;
  502. end;
  503. procedure TfrmMainForm.pnlSplitterMouseMove(Sender: TObject;
  504.   Shift: TShiftState; X, Y: Integer);
  505. begin
  506.   if boolResizeInProgress then
  507.   if pnlMovingSplitter.Visible then
  508.     pnlMovingSplitter.Left := X + pnlSendingSplitter.Left;
  509. end;
  510.  
  511. procedure TfrmMainForm.pnlSplitterMouseUp(Sender: TObject;
  512.   Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
  513. begin
  514.   otlnedbObjectToResize.Width := pnlMovingSplitter.Left - otlnedbObjectToResize.Left;
  515.     if otlnedbObjectToResize.Width < 5 then otlnedbObjectToResize.Width := 5;
  516.     if otlnedbObjectToResize.Width > pnlParentPanel.Width - 20 then
  517.       otlnedbObjectToResize.Width := pnlParentPanel.Width - 20;
  518.     pnlMovingSplitter.Visible := false;
  519.     boolResizeInProgress := false;
  520. end;
  521.  
  522. procedure TfrmMainForm.FormResize(Sender: TObject);
  523. begin
  524.   if FirstLoad then
  525.     if otlnedbObjectToResize.Width > pnlParentPanel.Width - 20 then
  526.       otlnedbObjectToResize.Width := pnlParentPanel.Width - 20;
  527.   Firstload := false;
  528. end;
  529.  
  530. {-------------------------------------------------}
  531. {used by demo to build database name -- not related to TDBOutline}
  532. function TfrmMainForm.GetDatabaseName: string;
  533. var
  534.   ExeDirName,
  535.   ExeFileName: array[0..100] of Char;
  536.   FileNamePtr: PChar;
  537.   NumChars: Word;
  538. begin
  539.   StrPCopy(ExeFileName, Application.ExeName);
  540.   FileNamePtr := StrRScan(ExeFileName, '\');
  541.   NumChars := FileNamePtr - ExeFileName;
  542.   StrLCopy(ExeDirName, ExeFileName, NumChars);
  543.   Result := StrPas(ExeDirName);
  544. end;
  545.  
  546. end.
  547.